package com.aiwu.pop;

import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;

import androidx.appcompat.app.AlertDialog;

import com.aiwu.ConfigManager;
import com.aiwu.PrefsHelper;
import com.aiwu.Util;
import com.aiwu.library.AiwuSimulator;
import com.aiwu.library.App;
import com.aiwu.library.util.DialogUtil;
import com.aiwu.library.util.ToastUtil;

import org.citra.citra_emu.NativeLibrary;
import org.citra.citra_emu.R;
import org.citra.citra_emu.activities.EmulationActivity;
import org.citra.citra_emu.features.settings.model.BooleanSetting;
import org.citra.citra_emu.features.settings.model.FloatSetting;
import org.citra.citra_emu.features.settings.model.IntSetting;
import org.citra.citra_emu.features.settings.model.Setting;
import org.citra.citra_emu.features.settings.model.SettingSection;
import org.citra.citra_emu.features.settings.model.Settings;
import org.citra.citra_emu.features.settings.model.StringSetting;
import org.citra.citra_emu.features.settings.ui.SettingsActivity;
import org.citra.citra_emu.features.settings.utils.SettingsFile;
import org.citra.citra_emu.utils.EmulationMenuSettings;
import org.citra.citra_emu.utils.Log;

/**
 * 快速设置弹窗
 */
public class FastSettingDialog extends AlertDialog implements View.OnClickListener {
    private CheckBox cbAudioStretch, cbAudioOutput, cbSwapScreens, cbShowFps, cbFontAcg, cbSkipSlowDraw, cbFmvHack, cbHideFloatView;
    public CheckBox cbQuickScreenLayout;
    private TextView tvInternalResolution, tvInternalResolutionMin, tvInternalResolutionMax, tvGameId;
    private SeekBar sbInternalResolution;

    private Settings mSettings = new Settings();
    private EmulationActivity activity;
    private String mGameId;
    private int font = PrefsHelper.FONT_INIT;

    public FastSettingDialog(EmulationActivity context, String gameId) {
        super(context, R.style.AiWuDialog);
        this.activity = context;
        mGameId = gameId;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
    }

    private void init() {
        setContentView(R.layout.dialog_fast_setting);
        setCancelable(true);
        setCanceledOnTouchOutside(true);
        setOnDismissListener(dialog -> {
            mSettings.saveSettings(null);
            NativeLibrary.ReloadSettings();
            if (font != PrefsHelper.getInstance().getFont()) {
                //需要切换字体
                boolean success = Util.changeFont(font);
                if (success) {
                    PrefsHelper.getInstance().setFont(font);
                    //弹窗提示要不重新开始游戏
                    DialogUtil.showTip(activity, "切换字体成功，是否重启游戏以适用字体？", v -> {
                        activity.reloadGame();
                    }, null);
                } else {
                    ToastUtil.toast("切换字库失败");
                }
            }
            if (cbHideFloatView.isChecked()) {
                //隐藏悬浮view
                activity.hideFloatingLayout();
                AiwuSimulator.setFastMenuLayoutVisibility(View.GONE);
            }
            activity.refreshFloatingScreenLayout();
        });
        initView();
        initEvent();
        initData();
    }

    private void initEvent() {
        cbAudioStretch.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                SettingSection audioSection = mSettings.getSection(Settings.SECTION_AUDIO);
                Setting audioStretch = audioSection.getSetting(SettingsFile.KEY_ENABLE_AUDIO_STRETCHING);
                IntSetting setting = setChecked(isChecked, audioStretch, SettingsFile.KEY_ENABLE_AUDIO_STRETCHING, Settings.SECTION_AUDIO);
                if (setting != null) {
                    audioSection.putSetting(setting);
                }
            }
        });
        cbAudioOutput.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                SettingSection audioSection = mSettings.getSection(Settings.SECTION_AUDIO);
                Setting audioOutput = audioSection.getSetting(SettingsFile.KEY_AUDIO_OUTPUT_ENGINE);
                StringSetting setting = enableSound(isChecked, audioOutput, SettingsFile.KEY_AUDIO_OUTPUT_ENGINE, Settings.SECTION_AUDIO);
                if (setting != null) {
                    audioSection.putSetting(setting);
                }
                AiwuSimulator.setSoundEnable(isChecked);
            }
        });

        cbSwapScreens.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                EmulationMenuSettings.setSwapScreens(isChecked);
                NativeLibrary.SwapScreens(isChecked, activity.getWindowManager().getDefaultDisplay().getRotation());
            }
        });
        cbShowFps.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                EmulationMenuSettings.setShowFps(isChecked);
                activity.updateShowFpsOverlay();
            }
        });

        cbFontAcg.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                font = isChecked ? PrefsHelper.FONT_ACG : PrefsHelper.FONT_INIT;
            }
        });
        cbSkipSlowDraw.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                NativeLibrary.SetRunningSettings(isChecked, cbFmvHack.isChecked());
            }
        });
        cbFmvHack.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                NativeLibrary.SetRunningSettings(cbSkipSlowDraw.isChecked(), isChecked);
            }
        });
        cbQuickScreenLayout.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (buttonView.isPressed()) {
                if (isChecked) {
                    cbQuickScreenLayout.setChecked(false);
                    new QuickScreenLayoutDialog(activity, FastSettingDialog.this).show();
                } else {
                    PrefsHelper.getInstance().removeQuickScreenLayout();
                }
            }
        });
        sbInternalResolution.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                displayInternalResolution(progress);
                if (fromUser) {
                    SettingSection rendererSection = mSettings.getSection(Settings.SECTION_RENDERER);
                    Setting resolutionFactor = rendererSection.getSetting(SettingsFile.KEY_RESOLUTION_FACTOR);
                    IntSetting setting = setSelectedValue(progress, resolutionFactor, SettingsFile.KEY_RESOLUTION_FACTOR, Settings.SECTION_RENDERER);
                    if (setting != null) {
                        rendererSection.putSetting(setting);
                    }
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    private void initData() {
//        if (!TextUtils.isEmpty(mGameId)) {
//            mSettings.loadSettings(mGameId, null);
//        } else {
        mSettings.loadSettings(null);
//        }
        SettingSection rendererSection = mSettings.getSection(Settings.SECTION_RENDERER);

        SettingSection audioSection = mSettings.getSection(Settings.SECTION_AUDIO);
        Setting audioStretch = audioSection.getSetting(SettingsFile.KEY_ENABLE_AUDIO_STRETCHING);
        Setting audioOutput = audioSection.getSetting(SettingsFile.KEY_AUDIO_OUTPUT_ENGINE);

        cbAudioStretch.setChecked(isChecked(audioStretch));
        cbAudioOutput.setChecked(isEnableSound(audioOutput));
        cbShowFps.setChecked(EmulationMenuSettings.getShowFps());
        cbSwapScreens.setChecked(EmulationMenuSettings.getSwapScreens());
        font = PrefsHelper.getInstance().getFont();
        cbFontAcg.setChecked(font == PrefsHelper.FONT_ACG);
        cbQuickScreenLayout.setChecked(PrefsHelper.getInstance().isQuickScreenLayout());

        boolean skipSlowDraw = NativeLibrary.GetRunningSettings()[0];
        boolean fmvHack = NativeLibrary.GetRunningSettings()[1];
        cbSkipSlowDraw.setChecked(skipSlowDraw);
        cbFmvHack.setChecked(fmvHack);

        Setting resolutionFactor = rendererSection.getSetting(SettingsFile.KEY_RESOLUTION_FACTOR);
        int progress = getSelectedValue(resolutionFactor, 1);
        displayInternalResolution(progress);
        sbInternalResolution.setProgress(progress);
        sbInternalResolution.setMin(1);
        sbInternalResolution.setMax(6);
        tvInternalResolutionMin.setText("1X");
        tvInternalResolutionMax.setText("6X");

        tvGameId.setText("ID:" + mGameId.toUpperCase());
    }

    public static IntSetting setChecked(boolean checked, Setting setting, String key, String section) {
        if (setting == null) {
            return new IntSetting(key, section, checked ? 1 : 0);
        } else {
            ((IntSetting) setting).setValue(checked ? 1 : 0);
            return null;
        }
    }

    public static StringSetting enableSound(boolean checked, Setting setting, String key, String section) {
        if (setting == null) {
            return new StringSetting(key, section, checked ? "auto" : "null");
        } else {
            ((StringSetting) setting).setValue(checked ? "auto" : "null");
            return null;
        }
    }

    /**
     * 是否启用音频输出
     *
     * @param s
     * @return
     */
    public static boolean isEnableSound(Setting s) {
        if (s == null) {
            return true;
        }
        try {
            StringSetting setting = (StringSetting) s;
            return !setting.getValue().equalsIgnoreCase("null");
        } catch (ClassCastException ignore) {
        }
        return false;
    }

    public static boolean isChecked(Setting s) {
        if (s == null) {
            return false;
        }

        // Try integer setting
        try {
            IntSetting setting = (IntSetting) s;
            return setting.getValue() == 1;
        } catch (ClassCastException ignore) {
        }

        // Try boolean setting
        try {
            BooleanSetting setting = (BooleanSetting) s;
            return setting.getValue();
        } catch (ClassCastException ignore) {
        }

        return false;
    }

    public static IntSetting setSelectedValue(int selection, Setting setting, String key, String section) {
        if (setting == null) {
            return new IntSetting(key, section, selection);
        } else {
            ((IntSetting) setting).setValue(selection);
            return null;
        }
    }

    public static int getSelectedValue(Setting setting, int defaultValue) {
        if (setting == null) {
            return defaultValue;
        }

        if (setting instanceof IntSetting) {
            IntSetting intSetting = (IntSetting) setting;
            return intSetting.getValue();
        } else if (setting instanceof FloatSetting) {
            FloatSetting floatSetting = (FloatSetting) setting;
            return Math.round(floatSetting.getValue());
        } else {
            Log.error("[SliderSetting] Error casting setting type.");
            return defaultValue;
        }
    }

    private void initView() {
        cbAudioStretch = findViewById(R.id.cb_audio_stretch);
        cbAudioOutput = findViewById(R.id.cb_audio_output);
        cbSwapScreens = findViewById(R.id.cb_swap_screens);
        cbShowFps = findViewById(R.id.cb_show_fps);
        cbFontAcg = findViewById(R.id.cb_font_acg);
        cbSkipSlowDraw = findViewById(R.id.cb_skip_slow_draw);
        cbFmvHack = findViewById(R.id.cb_fmv_hack);
        cbHideFloatView = findViewById(R.id.cb_hide_float_view);
        cbQuickScreenLayout = findViewById(R.id.cb_quick_screen_layout);
        tvInternalResolution = findViewById(R.id.tv_internal_resolution);
        tvInternalResolutionMin = findViewById(R.id.tv_internal_resolution_min);
        tvInternalResolutionMax = findViewById(R.id.tv_internal_resolution_max);
        sbInternalResolution = findViewById(R.id.sb_internal_resolution);
        tvGameId = findViewById(R.id.tv_game_id);
        findViewById(R.id.tv_audio_stretch).setOnClickListener(this);
        findViewById(R.id.layout_configure_controls).setOnClickListener(this);
        findViewById(R.id.layout_amiibo).setOnClickListener(this);
        findViewById(R.id.layout_screen_layout).setOnClickListener(this);
        findViewById(R.id.layout_more_setting).setOnClickListener(this);
        findViewById(R.id.tv_import_dlc_or_patch).setOnClickListener(this);
        findViewById(R.id.layout_import_dlc_or_patch).setOnClickListener(this);
        findViewById(R.id.tv_skip_slow_draw).setOnClickListener(this);
        findViewById(R.id.tv_fmv_hack).setOnClickListener(this);
        findViewById(R.id.tv_font_acg).setOnClickListener(this);
        findViewById(R.id.layout_skip_slow_draw).setVisibility(ConfigManager.getInstance().getSkipSlowDrawVis() ? View.VISIBLE : View.GONE);
        findViewById(R.id.layout_fmv_hack).setVisibility(ConfigManager.getInstance().getFmvHackVis() ? View.VISIBLE : View.GONE);
        findViewById(R.id.layout_shader_type).setOnClickListener(this);
        findViewById(R.id.layout_backup).setOnClickListener(this);
        findViewById(R.id.tv_hide_float_view).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_audio_stretch:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.audio_stretch),
                        App.getContext().getString(R.string.audio_stretch_description),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
            case R.id.layout_configure_controls:
                new ConfigureControlsDialog(activity, this).show();
                break;
            case R.id.layout_amiibo:
                new AmiiboDialog(activity, this).show();
                break;
            case R.id.layout_screen_layout:
                new SwitchScreenLayoutDialog(activity, this).show();
                break;
            case R.id.layout_more_setting:
                dismiss();
                SettingsActivity.launch(activity, SettingsFile.FILE_NAME_CONFIG, "");
                break;
            case R.id.tv_import_dlc_or_patch:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.emulation_import_dlc_or_patch),
                        App.getContext().getString(R.string.emulation_import_dlc_or_patch_desc),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
            case R.id.layout_import_dlc_or_patch:
                dismiss();
                activity.SelectDLCOrPatchFile();
                break;
            case R.id.tv_skip_slow_draw:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.skip_slow_draw),
                        App.getContext().getString(R.string.skip_slow_draw_desc),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
            case R.id.tv_fmv_hack:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.fmv_hack),
                        App.getContext().getString(R.string.fmv_hack_desc),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
            case R.id.tv_font_acg:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.emulation_font_acg),
                        App.getContext().getString(R.string.font_acg_desc),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
            case R.id.layout_shader_type:
                final SettingSection debugSection = mSettings.getSection(Settings.SECTION_DEBUG);
                final Setting shaderType = debugSection.getSetting(SettingsFile.KEY_SHADER_TYPE);
                int checkedItem = getSelectedValue(shaderType, 0);
                new AlertDialog.Builder(activity)
                        .setTitle(R.string.setting_shader_type)
                        .setSingleChoiceItems(R.array.shaderEntries, checkedItem, (dialog, which) -> {
                            dialog.dismiss();
                            int[] valuesArray = activity.getResources().getIntArray(R.array.shaderValues);
                            int newValue = valuesArray[which];
                            IntSetting setting = setSelectedValue(newValue, shaderType, SettingsFile.KEY_SHADER_TYPE, Settings.SECTION_DEBUG);
                            if (setting != null) {
                                debugSection.putSetting(setting);
                            }
                        })
                        .show();
                break;
            case R.id.layout_backup:
                dismiss();
                new BakListPop(activity).show();
                break;
            case R.id.tv_hide_float_view:
                DialogUtil.showTip(activity,
                        App.getContext().getString(R.string.hide_float_view),
                        App.getContext().getString(R.string.hide_float_view_desc),
                        App.getContext().getString(android.R.string.ok), null,
                        null, null
                );
                break;
        }
    }

    private void displayInternalResolution(int level) {
        switch (level) {
            case 1:
            default:
                tvInternalResolution.setText("1X(400x240)");
                break;
            case 2:
                tvInternalResolution.setText("2X(800x480)");
                break;
            case 3:
                tvInternalResolution.setText("3X(1200x720)");
                break;
            case 4:
                tvInternalResolution.setText("4X(1600x960)");
                break;
            case 5:
                tvInternalResolution.setText("5X(2000x1200)");
                break;
            case 6:
                tvInternalResolution.setText("6X(2400x1440)");
                break;
            case 7:
                tvInternalResolution.setText("7X(2800x1680)");
                break;
            case 8:
                tvInternalResolution.setText("8X(3200x1920)");
                break;
            case 9:
                tvInternalResolution.setText("9X(3600x2160)");
                break;
            case 10:
                tvInternalResolution.setText("10X(4000x2400)");
                break;
        }
    }

    public Settings getSettings() {
        return mSettings;
    }
}
